"use strict";
class Wacther {
    constructor(vm, value, cb) {
        this.vm = vm;
        this.value = value;
        this.cb = cb;
        this.oldValue = this.get();
    }
    //get 获取值触发
    get() {
        Dep.target = this;
        let value = complieUilt.getVal(this.value, this.vm);
        Dep.target = null;
        return value;
    }
    //set 设置值是触发
    updata() {
        let newValue = complieUilt.getVal(this.value, this.vm);
        if (newValue != this.oldValue) {
            this.cb(newValue);
        }
    }
}
class Dep {
    //target(str:string): string
    constructor() {
        this.watchers = [];
        //this.target = aa
    }
    add(watcher) {
        this.watchers.push(watcher);
    }
    notify() {
        this.watchers.forEach(watcher => {
            //watcher是一个个的实例观察者
            watcher.updata();
        });
    }
}
class Vue {
    constructor(opt) {
        this.el = opt.el,
            this.data = opt.data,
            new Observer(this.data); //数据劫持
        new Complie(this.el, this); //指令解析
    }
}
//数据劫持
class Observer {
    constructor(data) {
        this.observer(data);
    }
    observer(data) {
        if (data && typeof data === 'object') {
            for (let key in data) {
                //console.log(data[key])
                this.observerNode(data, key, data[key]);
            }
        }
    }
    observerNode(data, key, value) {
        this.observer(value);
        let dep = new Dep();
        Object.defineProperty(data, key, {
            get() {
                Dep.target && dep.add(Dep.target);
                return value;
            },
            set(newValue) {
                if (newValue != value) {
                    value = newValue;
                    dep.notify();
                }
            }
        });
    }
}
//指令解析
class Complie {
    constructor(el, vm) {
        this.vm = vm;
        this.el = this.isEmp(el) ? el : document.querySelector(el);
        //console.log(document.querySelector(el))
        //console.log(this.vm)
        let fragment = this.fragmentNode(this.el);
        //在内存中解析指令
        this.complie(fragment);
        //编译成功后再放入dom树页面
        this.el.append(fragment);
    }
    //把dom节点放入内存中
    fragmentNode(node) {
        //创建内存节点
        let fragment = document.createDocumentFragment();
        let fitstChild;
        while (fitstChild = node.firstChild) {
            fragment.append(fitstChild);
        }
        return fragment;
    }
    //判断是否是元素节点
    isEmp(node) {
        return node.nodeType === 1;
    }
    //编译指令(一)
    complie(node) {
        let childNodes = node.childNodes;
        //console.log(childNodes);
        [...childNodes].forEach(item => {
            if (this.isEmp(item)) {
                //就是元素节点
                this.complieEment(item);
                this.complie(item);
            }
            else {
                //就是文本节点
                this.complieText(item);
            }
        });
    }
    //编译元素节点上的指令
    complieEment(node) {
        //console.log(node)
        //后去元素上的属性
        let attributes = node.attributes;
        //console.log(attributes);
        [...attributes].forEach(item => {
            let { name, value } = item;
            //console.log(value)
            if (this.isEv(name)) {
                let [, model] = name.split('-');
                //console.log(model)
                complieUilt[model](node, value, this.vm);
                //console.log(value,'111111')
            }
        });
    }
    //判断是否以v-开头
    isEv(name) {
        return name.startsWith('v-');
    }
    //编译文本节点里的内容
    complieText(node) {
        //console.log(node)
        let content = node.textContent;
        //console.log(content)
        if (/\{\{(.+?)\}\}/.test(content)) {
            complieUilt.content(node, content, this.vm);
        }
    }
}
//工具类
let complieUilt = {
    //获取值
    getVal(value, vm) {
        //console.log(value)
        //[name,username]
        return value.split('.').reduce((prv, next) => {
            return prv[next];
        }, vm.data);
    },
    model(node, value, vm) {
        //console.log(node,value,vm)
        let newValue = this.getVal(value, vm);
        //console.log(newValue);
        new Wacther(vm, value, (newValue) => {
            fn(node, newValue);
        });
        let fn = this.Updatar.complieModel;
        fn(node, newValue);
    },
    html() {
    },
    content(node, value, vm) {
        console.log(node, value, vm);
        let newValue = value.replace(/\{\{(.+?)\}\}/g, (...ary) => {
            new Wacther(vm, ary[1], (newValue) => {
                fn(node, newValue);
            });
            return this.getVal(ary[1], vm);
        });
        console.log(newValue);
        let fn = this.Updatar.complieText;
        fn(node, newValue);
    },
    Updatar: {
        //更新属性节点的value
        complieModel(node, newValue) {
            node.value = newValue;
        },
        //更新文本节点里的值
        complieText(node, newValue) {
            node.textContent = newValue;
        }
    }
};